package com.fh.shop.api.order.biz;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.fh.shop.OrderDetail;
import com.fh.shop.Product;
import com.fh.shop.api.address.po.Address;
import com.fh.shop.api.cart.vo.CartItemVo;
import com.fh.shop.api.cart.vo.CartVo;
import com.fh.shop.api.common.Constant;
import com.fh.shop.api.common.ResponseEnum;
import com.fh.shop.util.ServerResponse;
import com.fh.shop.api.exception.StockException;
import com.fh.shop.api.mq.producer.OrderProducer;
import com.fh.shop.mapper.IOrderMapper;
import com.fh.shop.api.order.param.OrderParam;
import com.fh.shop.Order;
import com.fh.shop.api.util.KeyUtil;
import com.fh.shop.util.RedisUtil;
import com.fh.shop.mapper.IOrderDetailMapper;
import com.fh.shop.mapper.IProductMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service("orderService")
@Transactional(rollbackFor = Exception.class)
public class IOrderServiceImpl implements IOrderService {
    @Resource
    private IOrderMapper orderMapper;
    @Resource
    private IOrderDetailMapper orderDetailMapper;
    @Resource
    private IProductMapper productMapper;
    @Autowired
    private OrderProducer orderProducer;

    @Override
    public ServerResponse add(OrderParam orderParam) {
        //非空验证
        Integer payType = orderParam.getPayType();
        Long addressId = orderParam.getAddressId();
        Long memberId = orderParam.getMemberId();
        if (payType == null || addressId == null){
            return ServerResponse.error(ResponseEnum.ORDER_INFO_IS_NULL);
        }

        //验证购物车
        String cartKey = KeyUtil.CartKey(memberId);
        boolean exists = RedisUtil.exists(cartKey);
        if (!exists){
            return ServerResponse.error(ResponseEnum.ORDER_CART_IS_ERROR);
        }

        //验证收货地址
        String addrKey = KeyUtil.addrKey(memberId);
        String addrJSon = RedisUtil.get(addrKey);
        List<Address> addressList = JSON.parseArray(addrJSon, Address.class);
        Optional<Address> first = addressList.stream().filter(x -> x.getId().longValue() == addressId).findFirst();
        if (!first.isPresent()){
            return ServerResponse.error(ResponseEnum.ORDER_ADDR_IS_ERROR);
        }

        //获取收货地址
        Address address = first.get();

        //判断库存是否充足
        QueryWrapper<Product> productQueryWrapper = new QueryWrapper<>();
        String cartJson = RedisUtil.hget(cartKey, Constant.MEMBER_CART);
        CartVo cartVo = JSON.parseObject(cartJson, CartVo.class);
        List<CartItemVo> cartItemVoList = cartVo.getCartItemVoList();
        List<Long> productIdList = cartItemVoList.stream().map(x -> x.getId()).collect(Collectors.toList());
        productQueryWrapper.select("id","stock")
                           .in("id",productIdList);
        List<Product> productList = productMapper.selectList(productQueryWrapper);
        //创建空集合存放库存不足的商品名
        List<String> productNameList = new ArrayList<>();
        for (Product product : productList) {
            //判断相等商品的库存是否充足
            Optional<CartItemVo> cartItemVoOptional = cartItemVoList.stream().filter(x -> x.getId().longValue() == product.getId()).findFirst();
            CartItemVo cartItemVo = cartItemVoOptional.get();
            if (cartItemVo.getCount()>product.getStock()){
                productNameList.add(cartItemVo.getProductName());
            }
        }
        //响应给前台库存不足的商品
        if (productNameList.size()>0){
            //创建枚举特殊格式 %s 重载error方法 替换%s的内容
            // %s：String.format(格式,替换的内容)
            return ServerResponse.error(ResponseEnum.ORDER_STOCK_IS_ERROR, StringUtils.join(productNameList,","));
        }

        //减少库存
        for (CartItemVo cartItemVo : cartItemVoList) {
            Long productId = cartItemVo.getId();
            Long count = cartItemVo.getCount();
            int rows = productMapper.updateStock(productId, count);
            if (rows == 0){
                productNameList.add(cartItemVo.getProductName());
            }
        }
        if (productNameList.size()>0){
            throw new StockException(ResponseEnum.ORDER_STOCK_IS_ERROR,StringUtils.join(productNameList,","));
        }

        //插入订单表
        Order order = new Order();
        //使用string提供的雪花id
        String id = IdWorker.getIdStr();
        order.setId(id);
        Long totalCount = cartVo.getTotalCount();
        String totalSumPrice = cartVo.getTotalSumPrice();
        order.setTotalPrice(new BigDecimal(totalSumPrice));
        order.setTotalCount(totalCount);
        order.setMemberId(memberId);
        order.setCreateTime(new Date());
        order.setAddressId(addressId);
        order.setAddress(address.getAddress());
        order.setPhone(address.getPhone());
        order.setRecipinentName(address.getReceiver());
        order.setOrderStatus(Constant.OrderStatus.WAIT_PAY);
        order.setPayType(Constant.PAY_WAY);
        orderMapper.insert(order);

        //插入明细表
        List<OrderDetail> orderDetailList = cartItemVoList.stream().map(x -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(id);
            orderDetail.setCount(x.getCount());
            orderDetail.setImage(x.getImage());
            orderDetail.setPrice(new BigDecimal(x.getPrice()));
            orderDetail.setProductName(x.getProductName());
            orderDetail.setSubTotal(new BigDecimal(x.getTotalPrice()));
            orderDetail.setProductId(x.getId());
            return orderDetail;
        }).collect(Collectors.toList());
        orderDetailMapper.addBatchOrderDetail(orderDetailList);

        //删除redis缓存购物车
        RedisUtil.del(cartKey);

        //发送消息
        orderProducer.sendOrderMessage(id,Constant.ORDER_EXPIRED_TIME+"");

        return ServerResponse.success();
    }

    @Override
    public ServerResponse findOrder(Long memberId) {
        QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq("memberId",memberId);
        List<Order> orderList = orderMapper.selectList(orderQueryWrapper);
        return ServerResponse.success(orderList);
    }

}
